package com.sanmubird.mywebframework.indicator.domain.executor;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @author sam
 */
@Slf4j
public class SqlParser {

    private static final SpelExpressionParser PARSER = new SpelExpressionParser();
    private static final Map<String, Method> FUNCTIONS = new HashMap<>();

    static {
        List<Method> methods = Arrays.stream(SqlFunctions.class.getMethods())
                .filter(method -> Modifier.isStatic(method.getModifiers()))
                .collect(Collectors.toList());
        for (Method method : methods) {
            FUNCTIONS.put(method.getName(), method);
        }
    }

    /**
     * 解析sql
     * 表达式 参考文章： https://zhuanlan.zhihu.com/p/174786047
     *
     * @param targetSql 原始sql
     * @param params    参数
     * @return 解析后的sql
     */
    public String parse(String targetSql, JSONObject params) {
        EvaluationContext context = new StandardEvaluationContext();
        registerFunction(context);
        params.forEach(context::setVariable);
        Expression expression = PARSER.parseExpression(targetSql, ParserContext.TEMPLATE_EXPRESSION);
        return expression.getValue(context, String.class);
    }

    private void registerFunction(EvaluationContext context) {
        FUNCTIONS.forEach(context::setVariable);
    }
}
